import cv2
import math
import numpy as np
import matplotlib.pyplot as plt


# 1仿真运动模糊
def motion_process(image_size, motion_angle):
    PSF = np.zeros(image_size)
    center_position = (image_size[0] - 1) / 2
    slope_tan = math.tan(motion_angle * math.pi / 180)
    slope_cot = 1 / slope_tan
    if slope_tan <= 1:
        for i in range(15):
            offset = round(i * slope_tan)
            PSF[int(center_position + offset), int(center_position - offset)] = 1
        return PSF / PSF.sum()  # 对点扩散函数进行归一化亮度
    else:
        for i in range(15):
            offset = round(i * slope_cot)
            PSF[int(center_position - offset), int(center_position + offset)] = 1
        return PSF / PSF.sum()


# 对图像进行运动模糊
def make_blurred(input, PSF, eps):
    input_fft = np.fft.fft2(input)  # 二维数组的傅里叶变换
    PSF_fft = np.fft.fft2(PSF) + eps
    blurred = np.fft.ifft2(input_fft * PSF_fft)
    blurred = np.abs(np.fft.fftshift(blurred))
    return blurred


# 2运动模糊核矩阵
def motion_blur(image, degree=12, angle=80):
    image = np.array(image)
    # 生成任意角度的运动模糊kernel的矩阵，degree越大，模糊程度越高
    M = cv2.getRotationMatrix2D((degree / 2, degree / 2), angle, 1)
    motion_blur_kernel = np.diag(np.ones(degree))  # 输出矩阵的对角线元素
    # 放射变换函数
    motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, M, (degree, degree))
    motion_blur_kernel = motion_blur_kernel / degree
    blurred = cv2.filter2D(image, -1, motion_blur_kernel)
    cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX)  # 归一化函数
    blurred = np.array(blurred, dtype=np.uint8)
    return blurred


img = cv2.imread(r"C:\Users\Public\opencv\Figure\lena.jpg")

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 运动模糊函数
plt.subplot(221), plt.axis('off')
plt.title("Origin image"), plt.imshow(img_gray)
# 进行运动模糊处理
img_h, img_w = img.shape[0:2]
PSF = motion_process((img_h, img_w), 80)
blurred = np.abs(make_blurred(img_gray, PSF, 1e-3))

plt.subplot(222), plt.axis('off')
plt.title("Motion blurred")
plt.imshow(blurred)

img_blurred = motion_blur(img)  # 运动模糊核矩阵

plt.subplot(223), plt.axis('off')
plt.title("Origin image"), plt.imshow(img)

plt.subplot(224), plt.axis('off')
plt.title("Blurred image"), plt.imshow(img_blurred)

cv2.waitKey(0)
cv2.destroyAllWindows()



